﻿// ----------------------------------------------------------------------------------
// Sample Code from Fernando Machado Píriz's blog: http://fernandomachadopiriz.com
//
// <copyright company="Fernando Machado Píriz" file="NotifyHelper.cs">
// Copyright (c) Fernando Machado Píriz. Distributed under FSF's GPL v2. </copyright>
// ----------------------------------------------------------------------------------
// This code and information are provided "as is" without warranty of any kind,
// either expressed of implied, including but not limited to the implied warranties
// of merchantability and/or fitness for a particular purpose.
// ----------------------------------------------------------------------------------
namespace GivingAPresentation
{
    using System;
    using System.Windows;
    using GivingAPresentation.Commons;
    using Drawing = System.Drawing;
    using Forms = System.Windows.Forms;

    /// <summary>
    /// A helper class to manage an icon in the notification area. An instance of this class is created by the main window of an application.
    /// That instance manages the appearance and behavior of the main window.
    /// </summary>
    public class NotifyHelper : IDisposable
    {
        /// <summary>
        /// The initial state of the main window.
        /// </summary>
        private WindowState storedWindowState = WindowState.Normal;

        /// <summary>
        /// The main window managed by this notification helper.
        /// </summary>
        private Window mainWindow;

        /// <summary>
        /// The icon managed by this notification helper.
        /// </summary>
        private Forms.NotifyIcon notifyIcon;

        /// <summary>
        /// Initializes a new instance of the NotifyHelper class for the given main window.
        /// </summary>
        /// <param name="mainWindow">The main window managed by this notification helper.</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0",
            Justification = "The call to ExceptionHelper.CheckArgumentNotNull is validating the argument")]
        public NotifyHelper(Window mainWindow)
        {
            ExceptionHelper.CheckArgumentNotNull(mainWindow, "mainWindow");

            this.mainWindow = mainWindow;
            mainWindow.StateChanged += new EventHandler(this.Window_StateChanged);
            mainWindow.IsVisibleChanged += new DependencyPropertyChangedEventHandler(this.Window_IsVisibleChanged);
            mainWindow.Closed += new EventHandler(this.Window_Closed);
            this.CreateNotifyIcon();
        }

        /// <summary>
        /// Sets the tip of the balloon text shown by the icon in the notification area.
        /// </summary>
        internal string BalloonTipText
        {
            set
            {
                this.notifyIcon.BalloonTipText = value;
            }
        }

        /// <summary>
        /// Sets the title of the balloon text shown by the icon in the notification area.
        /// </summary>
        internal string BalloonTipTitle
        {
            set
            {
                this.notifyIcon.BalloonTipTitle = value;
            }
        }

        /// <summary>
        /// Sets the icon shown in the notification area. If this property is null no icon will be shown.
        /// </summary>
        internal Drawing.Icon Icon
        {
            set
            {
                this.notifyIcon.Icon = value;
            }
        }

        #region IDisposable Members

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        /// <param name="disposing">Indicates when this method is called by <code>Dispose</code>.</param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.notifyIcon != null)
                {
                    this.notifyIcon.Dispose();
                    this.notifyIcon = null;
                }
            }
        }

        #endregion

        /// <summary>
        /// Creates and configures the <code>NotifyIcon</code> instance managed by this helper. The text of the icon is the title of the
        /// main window.
        /// </summary>
        private void CreateNotifyIcon()
        {
            this.notifyIcon = new Forms.NotifyIcon();
            this.notifyIcon.Text = this.mainWindow.Title;
            this.notifyIcon.Click += new EventHandler(this.NotifyIcon_Click);
        }

        /// <summary>
        /// Fired when main window state changes. Shows the icon when the main window is minized and vice-versa.
        /// </summary>
        /// <param name="sender">The parameter is not used.</param>
        /// <param name="e">The parameter is not used.</param>
        private void Window_StateChanged(object sender, EventArgs e)
        {
            if (this.mainWindow.WindowState == WindowState.Minimized)
            {
                this.mainWindow.Hide();
                if (this.notifyIcon != null)
                {
                    this.notifyIcon.ShowBalloonTip(2000);
                }
            }
            else
            {
                this.storedWindowState = this.mainWindow.WindowState;
            }
        }

        /// <summary>
        /// Fired when the main window is hidden or shown. Updates the state of the notify icon accordingly.
        /// </summary>
        /// <param name="sender">The parameter is not used.</param>
        /// <param name="args">The parameter is not used.</param>
        private void Window_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs args)
        {
            this.CheckTrayIcon();
        }

        /// <summary>
        /// Fired when the main window is closed. Disposes the notify icon.
        /// </summary>
        /// <param name="sender">The parameter is not used.</param>
        /// <param name="e">The parameter is not used.</param>
        private void Window_Closed(object sender, EventArgs e)
        {
            if (this.notifyIcon != null)
            {
                this.notifyIcon.Dispose();
                this.notifyIcon = null;
            }
        }

        /// <summary>
        /// Fired when the user clicks the notify icon. Restores the main window state.
        /// </summary>
        /// <param name="sender">The parameter is not used.</param>
        /// <param name="e">The parameter is not used.</param>
        private void NotifyIcon_Click(object sender, EventArgs e)
        {
            this.mainWindow.Show();
            this.mainWindow.WindowState = this.storedWindowState;
        }

        /// <summary>
        /// Shows or hides the notification icon if the main windows is hidden or visible.
        /// </summary>
        private void CheckTrayIcon()
        {
            this.ShowTrayIcon(!this.mainWindow.IsVisible);
        }

        /// <summary>
        /// Shows or hides the notification icon.
        /// </summary>
        /// <param name="show">A value indicating if the notification icon should be hiden or shown.</param>
        private void ShowTrayIcon(bool show)
        {
            if (this.notifyIcon != null)
            {
                this.notifyIcon.Visible = show;
            }
        }
    }
}
